﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace THenu.TinyHourseLib.Win32API
{
    public class Win32API
    {
        #region 常数和结构
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_SYSKEYDOWN = 0x104;
        public const int WM_SYSKEYUP = 0x105;
        public const int WH_KEYBOARD_LL = 13;

        /// <summary>
        /// 声明键盘钩子的封送结构类型 
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            /// <summary>
            /// 表示一个在1到254间的虚似键盘码 
            /// </summary>
            public int vkCode; 
            /// <summary>
            /// 表示硬件扫描码 
            /// </summary>
            public int scanCode; 
            /// <summary>
            /// 标记
            /// </summary>
            public int flags;
            /// <summary>
            /// 时间
            /// </summary>
            public int time;
            /// <summary>
            /// 其他信息
            /// </summary>
            public int dwExtraInfo;
        }
        #endregion

        #region 系统钩子
        /// <summary>
        /// 
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
        
        /// <summary>
        /// 安装钩子的函数
        /// </summary>
        /// <param name="idHook"></param>
        /// <param name="lpfn"></param>
        /// <param name="hInstance"></param>
        /// <param name="threadId"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        /// <summary>
        /// 卸下钩子的函数
        /// </summary>
        /// <param name="idHook"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        /// <summary>
        /// 下一个钩挂的函数
        /// </summary>
        /// <param name="idHook"></param>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
        /*
         * 函数功能：该函数将指定的虚拟键码和键盘状态翻译为相应的字符或字符串。该函数使用由给定的键盘布局句柄标识的物理键盘布局和输入语言来翻译代码。
            函数原型：int ToAscii(UINT uVirtKey,UINT uScanCode,PBYTE lpKeyState,LPWORD lpChar,UINT uFlags);
            参数：
            nVirtkey：指定要翻译的虚拟键码。
            uScanCode：定义被翻译键的硬件扫描码。若该键处于up状态，则该值的最高位被设置。
            LpKeyState：指向包含当前键盘状态的一个256字节数组。数组的每个成员包含一个键的状态。若某字节的最高位被设置，则该键处于down状态。若最低位被设置，则表明该键被触发。在此函数中，仅有capslock键的触发位是相关的。NumloCk和scroll loCk键的触发状态将被忽略。
            LpChar：指向接受翻译所得字符或字符串的缓冲区。
            UFlags：定义一个菜单是否处于激活状态。若一菜单是活动的，则该参数为1，否则为0。
            返回值：若定义的键为死键，则返回值为负值。否则，返回值应为如下的值：
            O：对于当前键盘状态，所定义的虚拟键没有翻译。
            1：一个字符被拷贝到缓冲区。
            2：两个字符被拷贝到缓冲区。当一个存储在键盘布局中的死键（重音或双音字符）无法与所定义的虚拟键形成一个单字符时，通常会返回该值。
            备注：若键盘布局中原先存放了一个死键，则提供给ToAscii函数的参数可能不足以翻译虚拟键码。
            典型地，ToAscii函数执行基于虚拟键码的翻译。然而，在某些情况下，uScanCode参数的第15位可能被用来区分一个键的按下状态和释放状态。扫描码用于翻译Alt+数字键的键组合。
            尽管NUMLOCK事实影响键盘状态的触发键，TOAscii将忽略lpKeyState的触发设置（VK_NUMLOCK），因为仅uVirtKey参数就足以区分光标移动键（VL_HOME，INSERT,等等）和数字键（VK_DECIMAL，VK_NUMPADO_VK_NUMPAD9）。
            速查：Windows NT：3.1及以上版本；Windows：95及以上版本；Wiodows CE：不支持；头文件：Winuser.h；库文件：user32.lib。
            int toascii（int c）
            把c最高位舍去, 转换成7bit的unsigned char 类型使它符合ASCII表。
         */
        /// <summary>
        /// 该函数将指定的虚拟键码和键盘状态翻译为相应的字符或字符串
        /// </summary>
        /// <param name="uVirtKey"></param>
        /// <param name="uScanCode"></param>
        /// <param name="lpbKeyState"></param>
        /// <param name="lpwTransKey"></param>
        /// <param name="fuState"></param>
        /// <returns></returns>
        [DllImport("user32")]
        public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);
        [DllImport("user32")]
        public static extern int GetKeyboardState(byte[] pbKeyState);
        /// <summary>
        /// 获取一个应用程序或动态链接库的模块句柄
        /// </summary>
        /// <param name="lpModuleName"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
        #endregion
    }
}
